using System;
using System.IO;
using System.Xml;
using System.Linq;
using System.Windows.Forms;
using System.Reflection;
using System.Diagnostics;

using iPhoneUI.Shell;

namespace iPhoneUI
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [MTAThread]
        static void Main(string[] args)
        {
            // allow start page to be passed on the command line - useful for development
            string startPage = args != null && args.Length > 0 ? args[0] : "Home";
            Program.Run(startPage);
        }

        private static void Run(string startPage)
        {
            // load the shell config xml file
            string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase);
            path = Path.Combine(path, "ShellConfig.xml");
            Debug.Assert(File.Exists(path));

            XmlDocument doc = new XmlDocument();
            using (XmlReader reader = XmlReader.Create(path))
                doc.Load(reader);

            // modify the parsed Xml tree to reflect the runtime environment
            BindConfigToEnvironment(doc);

            WidgetHostForm form = new WidgetHostForm(new ShellConfig(doc.DocumentElement));
            form.GotoPage(startPage);
            Application.Run(form);
        }

        /// <summary>
        /// In this method any targetFolder nodes are expanded into items in the buttons collection
        /// One item is created for each lnk file in the specified folder
        /// If the tartgetFolder does not exist the containing page is removed
        /// </summary>
        /// <param name="config"></param>
        private static void BindConfigToEnvironment(XmlNode config)
        {
            // expand any widgets that specifiy a target folder
            foreach (XmlNode targetFolder in config.SelectNodes("//targetFolder"))
            {
                DirectoryInfo folder = new DirectoryInfo(targetFolder.InnerText);
                if (folder.Exists)
                {
                    XmlNode widgetConfig = targetFolder.SelectSingleNode("ancestor::widget");
                    string buttonImage = widgetConfig.Attributes["ButtonImage"] != null ? widgetConfig.Attributes["ButtonImage"].InnerText : string.Empty;

                    XmlNode list = widgetConfig.SelectSingleNode("property[@Name = 'Buttons']/list");
                    Debug.Assert(list != null);

                    // enumerate all the links in the folder and generate a shellCommand element
                    foreach (FileInfo file in folder.GetFiles("*.lnk").OrderBy(f => f.Name))
                    {
                        // skip shhortcus that are hidden or explicitly ignored
                        if ((file.Attributes & FileAttributes.Hidden) != FileAttributes.Hidden && IgnoreFile(widgetConfig, file.Name) == false)
                        {
                            XmlElement item = widgetConfig.OwnerDocument.CreateElement("object");
                            AddPropertyNode(item, "Text", Path.GetFileNameWithoutExtension(file.Name));
                            AddPropertyNode(item, "ImageName", buttonImage);
                            AddPropertyNode(item, "IconFilePath", file.FullName);
                            AddCmdLetNode(item, file.FullName);

                            list.AppendChild(item);
                        }
                    }
                }
                else
                {
                    // remove any shortcut pages whose target folder doesn't exist
                    XmlNode page = targetFolder.SelectSingleNode("ancestor::page");
                    page.ParentNode.RemoveChild(page);
                }
            }
        }

        private static void AddCmdLetNode(XmlNode item, string fullPath)
        {
            XmlNode cmdlet = AddPropertyNode(item, "CmdLet", string.Empty);
            XmlElement objectNode = item.OwnerDocument.CreateElement("object");
            objectNode.SetAttribute("Type", "iPhoneUI.Commands.StartProcessCmdLet");
            AddPropertyNode(objectNode, "FullPath", fullPath);
            
            cmdlet.AppendChild(objectNode);
        }

        private static XmlNode AddPropertyNode(XmlNode item, string name, string value)
        {
            XmlElement property = item.OwnerDocument.CreateElement("property");
            property.SetAttribute("Name", name);
            property.InnerText = value;
            item.AppendChild(property);

            return property;
        }

        private static bool IgnoreFile(XmlNode widgetConfig, string name)
        {
            return widgetConfig.SelectSingleNode(string.Format("ignore[text() = '{0}']", name)) != null;
        }
    }
}